// 'vscode'模块包含了VS Code extensibility API
// 按下述方式导入这个模块
import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';



// 一旦你的插件激活，vscode会立刻调用下述方法
export function activate(context: vscode.ExtensionContext) {
	// 用console输出诊断信息(console.log)和错误(console.error)
	// 下面的代码只会在你的插件激活时执行一次
	// console.log('Congratulations, your extension "my-first-extension" is now active!');
	// 入口命令已经在package.json文件中定义好了，现在调用registerCommand方法
	// registerCommand中的参数必须与package.json中的command保持一致

	// 获取VS Code的配置对象
	const config = vscode.workspace.getConfiguration();
	// 获取缩进配置
	const tabSize = config.get("editor.tabSize") ? Number(config.get("editor.tabSize")) : 4;
	const space = " ";
	const tab = space.repeat(tabSize);
	type ResultType = { lineText: string, formatStr: string, 'tryBegin': number, 'stackZ': string[], 'stackX': string[] };

	//快捷键格式化
	let formatter1 = vscode.commands.registerCommand('msf', () => {
		formatFileIndentation();
	});

	//右键菜单格式化
	let formatter2 = vscode.commands.registerCommand('ModuleSystemFormatter', (uri) => {
		// 把你的代码写在这里，每次命令执行时都会调用这里的代码
		// ...
		// 给用户显示一个消息提示
		// vscode.window.showInformationMessage('正在格式化代码，请稍等……');

		// 文件路径 
		const filePath = uri.path.substring(1);
		fs.stat(filePath, (err: any, stats: any) => {
			if (err) {
				vscode.window.showErrorMessage(`获取文件时遇到错误了${err}!!!`);
			}
			if (stats.isDirectory()) {
				vscode.window.showWarningMessage(`不能格式化文件夹，请重新选择！！！`);
			}
			if (stats.isFile()) {
				formatFileIndentation(filePath);
			}
		});
	});

	//格式化选择内容
	let formatter3 = vscode.commands.registerCommand('extension.formatSelectedContent', () => {
		// 获取当前活动编辑器
		const editor = vscode.window.activeTextEditor;
		// 检查是否有选定的内容
		if (editor && editor.selection) {
			// const selectedText = editor.document.getText(editor.selection);	// 获取选定的文本
			const startLine = editor.selection.start.line;	// 获取选定范围的起始行号
			const endLine = editor.selection.end.line + 1;	 // 获取选定范围的结束行号
			let startFormatLine: number = 0;	//格式化的行数从上一行开始
			let tryBegin: number = 0;	//首行缩进数

			if (startLine > 0) {
				let previousLineText = '';	//获取上一行的内容
				for (let lineIndex = startLine - 1; lineIndex > 0; lineIndex--) {
					previousLineText = editor.document.lineAt(lineIndex).text;
					//获取上一行的不为空行，也不是注释行的内容,
					if ('' !== previousLineText.trim() && previousLineText.trim()[0] !== '#') {
						startFormatLine = lineIndex;
						break;
					}
				}
				//如果上面的全部是空行
				if ('' === previousLineText.trim()) {
					tryBegin = 0;
					startFormatLine = startLine;
				} else {
					const spaceNum = previousLineText.length - previousLineText.trimStart().length;
					tryBegin = Math.floor(spaceNum / tabSize);
				}
			}
			let result: ResultType = { lineText: '', formatStr: '', 'tryBegin': tryBegin, 'stackZ': [], 'stackX': [] };
			editor.edit(editBuilder => {
				//循环选择的行首到行尾的数据，进行格式化替换
				for (let lineIndex = startFormatLine; lineIndex < endLine; lineIndex++) {
					const line = editor.document.lineAt(lineIndex);
					result['lineText'] = line.text;
					result = formatStrFun(result);
					// 替换行的内容为调整后的缩进
					if (startLine !== startFormatLine) { //过滤第一行，因为第一行是格式化依据的开始行，所以这一行不进行格式化
						editBuilder.replace(line.range, result['formatStr']);
					}
				}
			});
			// 提示格式化完成
			vscode.window.showInformationMessage('已格式化选定的内容');
		}
	});


	/**
	 * 自动补全
	 */
	let openSnippets = vscode.workspace.getConfiguration().get('open_snippets');
	const autoCompletion = vscode.languages.registerCompletionItemProvider('python', {
		provideCompletionItems
	}, '_');


	/**
	 * 自动提示实现
	 * @param document 
	 * @param position 
	 * @param token 
	 * @param context 
	 * @returns 
	 */
	function provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext) {

		// 当行前置的字符为关键字开头的时候
		let linePrefix = document.lineAt(position).text.substring(0, position.character);
		linePrefix = linePrefix.trim().replace('(', '');
		const dir = path.dirname(document.fileName);
		const headerOperationsDir = '/' + vscode.workspace.getConfiguration().get('hdader_operations.dir');	//获取operations的路径
		const openationFile = path.join(dir, headerOperationsDir, '/header_operations.py');

		// let completionItem: any[] = [];
		if (!linePrefix.includes('_')) { //下划线为触发条件，
			return undefined;
		}

		let rs = fs.readFileSync(openationFile).toString('utf8');
		let rTxt = rs.substring(0, rs.indexOf('lhs_operations'));
		let rTxtArr = rTxt.split(/\r\n|[\r\n]/);	//按换行符分割

		return rTxtArr.filter(t => {
			return t.indexOf('),') > -1 && t.includes('(' + linePrefix);;
		}).map(t => {
			let leftIndex = t.indexOf('(' + linePrefix);
			let rightIndex = t.indexOf('),', leftIndex);
			let ptxt = t.substring(leftIndex, rightIndex + 2);
			// console.log(ptxt)
			return new vscode.CompletionItem(ptxt, vscode.CompletionItemKind.Method);
		});


		// fs.readFile(openationFile,'utf8',(err,rs)=>{
		// 	if (err) {throw err;}
		// 	let rTxt = rs.substring(0,rs.indexOf('lhs_operations'));
		// 	let rTxtArr = rTxt.split(/\r\n|[\r\n]/);	//按换行符分割
		// rTxtArr.forEach(v=>{
		// 	if(v.includes('('+linePrefix)){
		// 		let leftIndex = v.indexOf('('+linePrefix);
		// 		let rightIndex = v.indexOf('),',leftIndex);
		// 		let ptxt = v.substring(leftIndex,rightIndex+2);
		// 		console.log(ptxt);
		// 		completionItem.push(new vscode.CompletionItem(ptxt, vscode.CompletionItemKind.Method));
		// 	}
		// });
		// });


		// if (completionItem.length === 0) {
		// 	return undefined;
		// }
		// // 返回选项
		// return completionItem;
	}


	/**格式化整个文档内容**/
	function formatFileIndentation(fileUri: string | any = null) {
		// 获取当前活动的编辑器
		const editor = vscode.window.activeTextEditor;

		// 检查是否是python文件
		if (editor && editor.document.languageId !== 'python') {
			vscode.window.showErrorMessage('该命令只能在python文件中使用,该命令是用来格式化module system代码的');
			return;
		}

		if (editor) {
			// 获取当前编辑文件的URI
			fileUri = fileUri ? fileUri : editor.document.uri.path;
			const fileName = path.basename(fileUri);

			// 格式化文件缩进
			editor.edit((editBuilder) => {
				const document = editor.document;
				const firstLine = document.lineAt(0);
				const lastLine = document.lineAt(document.lineCount - 1);
				// const range = new vscode.Range(firstLine.range.start, lastLine.range.end);
				let result: ResultType = { lineText: '', formatStr: '', 'tryBegin': 0, 'stackZ': [], 'stackX': [] };

				vscode.window.withProgress({
					// 进度显示类型, Notification(右下角通知和进度) | Window(状态栏转圈) | SourceControl(源代码控制栏图标和进度)
					location: vscode.ProgressLocation.Notification,
					title: `${fileName}>>>`,
					cancellable: true	// 显示取消按钮
				}, (progress, token) => {
					// 取消按钮回调
					token.onCancellationRequested(() => {
						vscode.window.showInformationMessage("取消成功");
						return;
					});
					progress.report({ increment: 0 }); //初始化
					// 根据缩进配置调整每行的缩进
					for (let lineIndex = firstLine.lineNumber; lineIndex <= lastLine.lineNumber; lineIndex++) {
						const line = document.lineAt(lineIndex);
						result['lineText'] = line.text;
						result = formatStrFun(result);
						// 替换行的内容为调整后的缩进
						editBuilder.replace(line.range, result['formatStr']);
						progress.report({
							increment: lineIndex / lastLine.lineNumber,	//进度条增量
							message: `${(Math.floor(lineIndex / lastLine.lineNumber * 100) === 100 ? '格式化完成！' : '正在格式化代码，请稍等……')}`
						});
					}
					// progress.report({ increment: 100, message: "格式化完成！" });

					// 3秒后关闭
					return new Promise<void>(resolve => {
						setTimeout(resolve, 3000);
					});
				});
			});
		}
	}


	/**
	 * 处理每行的缩进
	 * @param args 参数
	 * @returns 
	 */
	function formatStrFun(args: ResultType): ResultType {
		let { lineText, formatStr, tryBegin, stackZ, stackX } = args;
		if (lineText.trim()[0] === '#') { 	//注释的不进行处理
			lineText = (tab.repeat(tryBegin) + lineText.trim());
			let result: ResultType = { lineText: '', formatStr: lineText, 'tryBegin': tryBegin, 'stackZ': stackZ, 'stackX': stackX };
			return result;
		}
		formatStr = '';	//初始化
		let indexOf = lineText.indexOf('#');

		let str = lineText.trim(); //字符部分
		let annotation = '';	//注释部分

		//存在#符号
		if (indexOf > -1) {
			str = lineText.substring(0, indexOf).trim(); //代码部分
			annotation = lineText.substring(lineText.indexOf('#')).trim();	//注释部分
			let markCount1 = (lineText.match(/\"/g) || []).length;
			let markCount2 = (lineText.match(/\'/g) || []).length;
			let count = 0;
			if (markCount1 % 2 === 0) {
				count = (str.match(/\"/g) || []).length;
			} else if (markCount2 % 2 === 0) {
				count = (str.match(/\'/g) || []).length;
			}
			if (count !== 0 && count % 2 !== 0) { //如果代码部分还存在单引号或双引号（字符符号），且不是偶数，那么说明#是字符串的一部分
				str = lineText.trim();	//不进行拆分。#号为字符串的一部分
				annotation = '';
			}
		}

		/**
		 * 获取需要缩进的情况
		 * 单独的中括号，小括号，判断的开始，循环的开始都是缩进的开始
		 */
		if (str === '[' || str.includes('= [') || str.includes('=[')) {
			stackZ.push('[+');
		} else if (str === '(') {
			stackX.push('(+');
		} else if (str.includes('[')) {
			stackZ.push('[');
		} else if (str.includes('(')) {
			stackX.push('(');
		}

		if (str === '[' || str.includes('= [') || str.includes('=[')) {
			tryBegin++;
			formatStr = (tab.repeat((tryBegin - 1)) + str);
		} else if (str === '(') {
			tryBegin++;
			formatStr = (tab.repeat((tryBegin - 1)) + str);
		} else if (str.includes('try_begin')
			|| str.includes('try_for_range')
			|| str.includes('try_for_range_backwards')
			|| str.includes('try_for_parties')
			|| str.includes('mtry_for_prop_instances')
			|| str.includes('try_for_players')
			|| str.includes('try_for_agents')) {
			tryBegin++;
			formatStr = (tab.repeat((tryBegin - 1)) + str) + annotation;;
		} else if (str.includes('else_try') || str.includes('else_try_begin')) {
			formatStr = (tab.repeat((tryBegin - 1)) + str) + annotation;
		} else if (str.includes('try_end') || str.includes('end_try')) {
			tryBegin--;
			formatStr = (tab.repeat(tryBegin) + str) + annotation;
		}
		else {
			formatStr = (tab.repeat(tryBegin) + str) + annotation;
		}

		if (str.includes(']')) {
			let popItem = stackZ.pop();
			if (popItem === '[+') {
				tryBegin--;
				formatStr = (tab.repeat(tryBegin) + str) + annotation;
			}
		}
		if (str.includes(')')) {
			let popItem = stackX.pop();
			if (popItem === '(+') {
				tryBegin--;
				formatStr = (tab.repeat(tryBegin) + str) + annotation;
			}
		}
		let result: ResultType = { lineText: lineText, formatStr: formatStr, 'tryBegin': tryBegin, 'stackZ': stackZ, 'stackX': stackX };
		return result;
	}


	//给插件订阅事件
	context.subscriptions.push(formatter1, formatter2, formatter3);
	if (openSnippets) { context.subscriptions.push(autoCompletion); }
}

//释放插件时触发
export function deactivate() { }